package com.tj.collection.controller.lending;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Page;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.exception.common.ApplicationException;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.tj.collection.aop.anno.VisitorAccessible;
import com.tj.collection.bean.ApiResponse;
import com.tj.collection.bean.ModuleResponse;
import com.tj.collection.bean.RedisKey;
import com.tj.collection.common.RequestLocalInfo;
import com.tj.collection.controller.lending.request.ClOutboundQueryRequest;
import com.tj.collection.controller.lending.response.ClOutboundQueryResponse;
import com.tj.collection.db.dao.ClOutboundBatchDao;
import com.tj.collection.db.dao.ClOutboundDetailDao;
import com.tj.collection.db.dao.ClReceiverDao;
import com.tj.collection.db.dao.ClReceiverDetailDao;
import com.tj.collection.db.entity.ClOutboundBatchEntity;
import com.tj.collection.db.entity.ClOutboundDetailEntity;
import com.tj.collection.db.entity.ClReceiverDetailEntity;
import com.tj.collection.db.entity.ClReceiverEntity;
import com.tj.collection.db.entity.business.ClOutboundEntity;
import com.tj.collection.db.entity.business.ClOutboundInfoEntity;
import com.tj.collection.enums.OutboundBatchStatusEnum;
import com.tj.collection.enums.OutboundDetailStatusEnum;
import com.tj.collection.integration.MessageIntegrationService;
import com.tj.collection.service.ClOutboundService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;

/**
 * 用于三方回调
 * User: pavan
 * Date: 2020/2/26
 * Time: 上午9:36
 */
@RestController
@RequestMapping("/collection/outbound")
public class ClOutboundController {

    private static final Log LOGGER = LogFactory.getLog(ClOutboundController.class);
    @Autowired
    private ClOutboundBatchDao clOutboundBatchDao;
    @Autowired
    private ClOutboundDetailDao clOutboundDetailDao;
    @Autowired
    private ClOutboundService clOutboundService;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private MessageIntegrationService messageIntegrationService;
    @Autowired
    private ClReceiverDao clReceiverDao;
    @Autowired
    private ClReceiverDetailDao clReceiverDetailDao;

    /**
     * 拨打任务
     *
     * @return
     */
    @RequestMapping("/addPlan/submit")
    public ApiResponse addPlanCall(@RequestBody JSONObject request) {
        Integer overdueDays = request.getInteger("overdueDays");
        Integer limit = request.getInteger("callSize");
        if (overdueDays == null) {
            throw new ApplicationException("Params error!");
        }
        String merchantCode = RequestLocalInfo.getCurrentAdmin().getMerchantCode();

        String key = RedisClient.format(RedisKey.OUTBOUND_DATE_KEY, merchantCode, DateUtil.getDate(new Date()), (overdueDays + ""), limit + "");
        String value = redisClient.get(key);
        if (value != null) {
            throw new ApplicationException(merchantCode + "has triggered today," + key);
        }
        //加锁一天
        redisClient.set(key, key, 24 * 60 * 60);

        clOutboundService.call(merchantCode, overdueDays, limit);
        return new ApiResponse<>();
    }

    /**
     * 拨打任务 外部使用
     *
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/addPlan/import")
    public ApiResponse addExternalPlanCall(@RequestBody JSONObject request) {
        JSONArray orderList = request.getJSONArray("orderList");
        if (orderList == null || orderList.size() == 0) {
            return new ApiResponse<>("无需处理");
        }
        LOGGER.info("本次传入订单数,{},request:{}", orderList.size(), JSON.toJSONString(request));
        String merchantCode = request.getString("merchantCode");
        if (StringUtils.isEmpty(merchantCode)) {
            merchantCode = "LOANBEE";
        }
        Integer overdueDays = request.getInteger("overdueDays");
        String batch = "D_" + merchantCode + "_" + (overdueDays == null ? 0 : overdueDays) + "_" + DateUtil.getDate(new Date(), "yyyyMMddHHmmss");
        List<ClOutboundEntity> entityList = new ArrayList<>();
        for (int i = 0; i < orderList.size(); i++) {
            JSONObject item = orderList.getJSONObject(i);
            ClOutboundEntity entity = new ClOutboundEntity();
            entity.setTradeNo(item.getString("tradeNo"));
            entity.setMobile(item.getString("mobile"));
            entity.setRepaymentCapital(item.getBigDecimal("repaymentCapital").setScale(2, BigDecimal.ROUND_HALF_UP));
            entity.setRepaymentDate(DateUtil.getDate(item.getString("repaymentDate"), "yyyy-MM-dd"));
            entityList.add(entity);
        }
        clOutboundService.doCall(merchantCode, entityList, batch);
        return new ApiResponse<>();
    }

    /**
     * 拨打任务 批次回调信息
     *
     * @return
     */
    @RequestMapping("/addPlan/count")
    public ApiResponse<ClOutboundQueryResponse> callCount(@RequestBody JSONObject request) {
        Integer overdueDays = request.getInteger("overdueDays");
        if (overdueDays == null) {
            throw new ApplicationException("Params error!");
        }
        String merchantCode = RequestLocalInfo.getCurrentAdmin().getMerchantCode();
        int count = clOutboundService.countOutbound(merchantCode, overdueDays);
        return new ApiResponse<>(new ClOutboundQueryResponse(count));
    }

    /**
     * 拨打记录列表
     *
     * @return
     */
    @RequestMapping("/call/list")
    public ModuleResponse<ClOutboundQueryResponse> callList(@RequestBody ClOutboundQueryRequest clOutboundQueryRequest, Page page) {
        Integer adminId = RequestLocalInfo.getCurrentAdmin().getId().intValue();
        String merchantCode = RequestLocalInfo.getCurrentAdmin().getMerchantCode();

        Map<String, Object> params = new HashMap<>();
        params.put("merchantCode", merchantCode);
        if (StringUtils.isNotEmpty(clOutboundQueryRequest.getStartDate()) && StringUtils.isNotEmpty(clOutboundQueryRequest.getEndDate())) {
            params.put("startDate", DateUtil.getDate(clOutboundQueryRequest.getStartDate(), "yyyy-MM-dd"));
            params.put("endDate", DateUtil.addDate(DateUtil.getDate(clOutboundQueryRequest.getEndDate(), "yyyy-MM-dd"), 1));
        }
        if (StringUtils.isNotEmpty(clOutboundQueryRequest.getType())) {
            params.put("type", clOutboundQueryRequest.getType());
        }
        if (clOutboundQueryRequest.getStatus() != null) {
            params.put("status", clOutboundQueryRequest.getStatus());
        }
        if (page != null) {
            params.put("page", page);
        }
        LOGGER.info("拨打列表查询参数,merchantCode:{},adminId:{},params:{}", merchantCode, adminId, JSON.toJSONString(params));
        List<ClOutboundInfoEntity> clOutboundInfoEntityList = clOutboundDetailDao.selectClOutboundInfoListByParams(params);
        return new ModuleResponse<>(new ClOutboundQueryResponse(clOutboundInfoEntityList), page);
    }

    /**
     * 拨打记录列表 单条详情
     *
     * @return
     */
    @RequestMapping("/call/detail")
    public ApiResponse<ClOutboundQueryResponse> callDetail(@RequestBody ClOutboundQueryRequest clOutboundQueryRequest) {
        if (StringUtils.isEmpty(clOutboundQueryRequest.getBatchNo()) || StringUtils.isEmpty(clOutboundQueryRequest.getMobile())) {
            throw new ApplicationException("params error");
        }
        ClOutboundBatchEntity clOutboundBatchEntity = clOutboundBatchDao.selectClOutboundBatchByBatchName(clOutboundQueryRequest.getBatchNo());
        if (clOutboundBatchEntity == null) {
            throw new ApplicationException("批次号不存在");
        }
        ClOutboundDetailEntity clOutboundDetailEntity = clOutboundDetailDao.selectClOutboundDetailByMobile(clOutboundQueryRequest.getBatchNo(), clOutboundQueryRequest.getMobile());
        if (clOutboundBatchEntity == null) {
            throw new ApplicationException("手机号单条记录不存在");
        }
        return new ApiResponse<>(new ClOutboundQueryResponse(clOutboundBatchEntity, clOutboundDetailEntity));
    }

    /**
     * 拨打任务 批次回调信息
     *
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/batch/callback")
    public ApiResponse planBatchCallback(@RequestBody JSONObject request) {
        LOGGER.info("接收批次回调信息,request:{}", request.toJSONString());

        Integer code = request.getInteger("code");

        if (code == null || code != 0) {
            throw new ApplicationException("校验失败");
        }
        try {
            JSONObject bodyObj = request.getJSONObject("body");
            String batchName = bodyObj.getString("batchName");
            Integer acceptCount = bodyObj.getInteger("acceptCount");
            Integer endCount = bodyObj.getInteger("endCount");
            Integer planCount = bodyObj.getInteger("planCount");
            Integer successCount = bodyObj.getInteger("successCount");
            Integer failCount = bodyObj.getInteger("failCount");
            String failList = bodyObj.getString("failList");

            ClOutboundBatchEntity clOutboundBatchEntity = clOutboundBatchDao.selectClOutboundBatchByBatchName(batchName);
            if (clOutboundBatchEntity == null) {
                throw new ApplicationException("批次号不存在");
            }

            clOutboundBatchEntity.setAcceptCount(acceptCount);
            clOutboundBatchEntity.setEndCount(endCount);
            clOutboundBatchEntity.setPlanCount(planCount);
            clOutboundBatchEntity.setSuccessCount(successCount);
            clOutboundBatchEntity.setFailCount(failCount);
            clOutboundBatchEntity.setStatus(OutboundBatchStatusEnum.CALL_COMPLETION.getStatus());
            clOutboundBatchDao.updateByPrimaryKey(clOutboundBatchEntity);
            LOGGER.info("接收批次回调信息处理成功,batchName:{}", batchName);
            if (StringUtils.isNotEmpty(failList)) {
                LOGGER.error("批次回调存在拨号失败列表,batchName:{},failList:{}", batchName, failList);
            }
        } catch (ApplicationException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("planBatchCallback处理失败,request:{}", request.toJSONString(), e);
            throw new ApplicationException("处理异常");
        }
        return new ApiResponse<>();
    }

    /**
     * 拨打任务 单笔回调信息
     *
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/detail/callback")
    public ApiResponse planDetailCallback(@RequestBody JSONObject request) {
        LOGGER.info("接收单条回调信息,request:{}", request.toJSONString());
        Integer code = request.getInteger("code");
        if (code == null || code != 0) {
            throw new ApplicationException("校验失败");
        }
        try {
            JSONObject bodyObj = request.getJSONObject("body");
            String batchName = bodyObj.getString("batchName");
            String phone = bodyObj.getString("phone");
            if (StringUtils.isEmpty(phone)) {
                phone = bodyObj.getString("phoneNo");
            }
            String attach = bodyObj.getString("attach");
            String tradeNo = null;
            if (StringUtils.isNotEmpty(attach)) {
                tradeNo = attach;
            }
            Date callStartTime = bodyObj.getDate("callStartTime");
            Date answerTime = bodyObj.getDate("answerTime");
            Integer duration = bodyObj.getInteger("duration");
            Integer billSec = bodyObj.getInteger("billSec");
            Date hangupTime = bodyObj.getDate("hangupTime");
            Integer hangupDirection = bodyObj.getInteger("hangupDirection");
            String accurateIntent = bodyObj.getString("accurateIntent");
            String reason = bodyObj.getString("reason");
            String remarks = bodyObj.getString("remarks");
            Integer freason = bodyObj.getInteger("freason");
            String detailList = bodyObj.getString("detailList");

            ClOutboundDetailEntity clOutboundDetailEntity = null;
            if (StringUtils.isNotEmpty(batchName) && StringUtils.isNotEmpty(phone)
                    && StringUtils.isNotEmpty(tradeNo)) {
                clOutboundDetailEntity = clOutboundDetailDao.selectClOutboundDetailByMobile(batchName, phone, tradeNo);
            } else if (StringUtils.isNotEmpty(batchName) && StringUtils.isNotEmpty(phone)) {
                clOutboundDetailEntity = clOutboundDetailDao.selectClOutboundDetailByMobile(batchName, phone);
            }
            if (clOutboundDetailEntity == null) {
                throw new ApplicationException("手机号单条记录不存在");
            }

            clOutboundDetailEntity.setCallStartTime(callStartTime)
                    .setAnswerTime(answerTime)
                    .setDuration(duration)
                    .setBillSec(billSec)
                    .setHangupTime(hangupTime)
                    .setHangupDirection(hangupDirection)
                    .setAccurateIntent(accurateIntent)
                    .setReason(reason)
                    .setRemarks(remarks)
                    .setFreason(freason)
                    .setDetailList(StringUtils.isEmpty(detailList) ? "" : (detailList.length() > 2048 ? detailList.substring(0, 2048) : detailList))
                    .setStatus(OutboundDetailStatusEnum.CALL_SUCCESS.getStatus());
            clOutboundDetailDao.updateByPrimaryKey(clOutboundDetailEntity);
            LOGGER.info("接收单条回调信息处理成功,batchName:{},phone:{}", batchName, phone);

            try {
                tradeNo = clOutboundDetailEntity.getTradeNo();
                ClReceiverEntity clReceiverEntity = clReceiverDao.selectLastByOrderNo(tradeNo);
                ClReceiverDetailEntity clReceiverDetailEntity = clReceiverDetailDao.selectOneByCollectionNo(clReceiverEntity.getCollectionNo());
                messageIntegrationService.sendBillNote(
                        clReceiverEntity.getUserCode(), clReceiverEntity.getOrderNo(),
                        clReceiverDetailEntity.getMobile(), clReceiverDetailEntity.getName(), clReceiverDetailEntity.getRepaymentDate(),
                        clReceiverDetailEntity.getBorrowCapital().toString()
                );
            } catch (Exception e) {
                LOGGER.error("接收单条回调,发送短信失败,batchName:{},phone:{},tradeNo:{}", batchName, phone, tradeNo);
            }

        } catch (ApplicationException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("planDetailCallback处理失败,request:{}", request.toJSONString(), e);
            throw new ApplicationException("处理异常");
        }
        return new ApiResponse<>();
    }

    /**
     * 拨打任务 批次回调信息
     *
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/query/callback")
    public ApiResponse queryCallback(@RequestBody JSONObject request) {
        LOGGER.info("接收批次回调信息,request:{}", request.toJSONString());
        return new ApiResponse<>();
    }

    /**
     * 无逾期AI电话
     *
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/noOverdueCall")
    public ApiResponse noOverdueCall() {
        try {
            clOutboundService.noOverdueCall();
        } catch (Exception e) {
            LOGGER.error("无逾期AI电话沟通出错。。。");
            return new ApiResponse("Error");
        }

        return new ApiResponse("Success");
    }

    /**
     * 无逾期电话够短信发送
     *
     * @param request
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/noOverdueCall/callBack")
    public ApiResponse noOverdueCallBack(@RequestBody JSONObject request) {
        LOGGER.info("单次回调，发短信开始 。。。。。。。。。。。。");
        try {
            clOutboundService.noOverdueCallBack(request);
        } catch (Exception e) {
            LOGGER.error("无逾期AI发短信出错。。。");
            return new ApiResponse("Error");
        }
        return new ApiResponse("Success");

    }

    /**
     * 逾期AI电话
     *
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/overdueCall")
    public ApiResponse overdueCall(@RequestParam(name = "min") int min,
                                   @RequestParam(value = "max") int max,
                                   @RequestParam(value = "code") String code,
                                   @RequestParam(value = "dayNum") int dayNum) {
        try {
            clOutboundService.overdueCall(min, max, code, dayNum);
        } catch (Exception e) {
            LOGGER.error("逾期AI电话c催收。。。");
            return new ApiResponse("Error");
        }

        return new ApiResponse("Success");
    }

    /**
     * 逾期电话回调
     *
     * @param request
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/overdueCall/callBack")
    public ApiResponse overdueCall(@RequestBody JSONObject request) {
        LOGGER.info("逾期电话催收单次回调 。。。。。。。。。。。。");
        try {
            clOutboundService.overdueCallBack(request);
        } catch (Exception e) {
            LOGGER.error("逾期电话单次回调出错。。。");
            return new ApiResponse("Error");
        }
        return new ApiResponse("Success");

    }

    /**
     * 批次回调
     *
     * @param request
     * @return
     */
    @VisitorAccessible
    @RequestMapping("/plan/noOverdueCall/callBackBatch")
    public ApiResponse noOverdueCallBackBatch(@RequestBody JSONObject request) {
        LOGGER.info("批次回调 成功 。。。。。。。。。。。");

        return new ApiResponse("批次回调 成功 。。。。。。。。。。。");

    }
}
